package com.orange.project.news;

import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.corpus.tag.Nature;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 新闻热点分析器
 * 功能：提取热点词汇 + 通过词汇定位新闻
 */
public class NewsHotspotAnalyzer {

    // 新闻数据存储
    private List<NewsItem> newsList;

    // 词频统计
    private Map<String, Integer> wordFrequency;

    // 倒排索引：词汇 -> 包含该词汇的新闻索引列表
    private Map<String, List<Integer>> invertedIndex;

    // 停用词集合
    private Set<String> stopWords;

    // 需要保留的词性
    private Set<Nature> allowedNatures;

    public NewsHotspotAnalyzer() {
        this.newsList = new ArrayList<>();
        this.wordFrequency = new HashMap<>();
        this.invertedIndex = new HashMap<>();
        initStopWords();
        initAllowedNatures();
    }

    /**
     * 新闻条目类
     */
    public static class NewsItem {
        private String id;
        private String title;
        private String content;
        private Date publishTime;

        public NewsItem(String id, String title, String content, Date publishTime) {
            this.id = id;
            this.title = title;
            this.content = content;
            this.publishTime = publishTime;
        }

        // getters and setters
        public String getId() { return id; }
        public String getTitle() { return title; }
        public String getContent() { return content; }
        public Date getPublishTime() { return publishTime; }

        @Override
        public String toString() {
            return String.format("News{id=%d, title='%s'}", id, title);
        }
    }

    /**
     * 热点词汇结果类
     */
    public static class HotspotResult {
        private String word;
        private int frequency;
        private List<NewsItem> relatedNews;

        public HotspotResult(String word, int frequency, List<NewsItem> relatedNews) {
            this.word = word;
            this.frequency = frequency;
            this.relatedNews = relatedNews;
        }

        // getters
        public String getWord() { return word; }
        public int getFrequency() { return frequency; }
        public List<NewsItem> getRelatedNews() { return relatedNews; }

        @Override
        public String toString() {
            return String.format("Hotspot{word='%s', frequency=%d, newsCount=%d}",
                    word, frequency, relatedNews.size());
        }
    }

    /**
     * 初始化停用词
     */
    private void initStopWords() {
        stopWords = new HashSet<>(Arrays.asList(
                "的", "了", "在", "是", "我", "有", "和", "就", "不", "人", "都", "一", "一个", "上", "也", "很", "到", "说", "要", "去", "你", "会", "着", "没有", "看", "好", "自己", "这", "那"
        ));
    }

    /**
     * 初始化允许的词性
     */
    private void initAllowedNatures() {
        allowedNatures = new HashSet<>(Arrays.asList(
                Nature.n,      // 名词
                Nature.nr,     // 人名
                Nature.ns,     // 地名
                Nature.nt,     // 机构名
                Nature.nz,     // 其他专名
                Nature.v,      // 动词
                Nature.vn,     // 动名词
                Nature.a,      // 形容词
                Nature.d,      // 副词
                Nature.m,      // 数词
                Nature.ng      // 名词性语素
        ));
    }

    /**
     * 添加新闻数据
     */
    public void addNews(List<NewsItem> newsItems) {
        this.newsList.addAll(newsItems);
        rebuildIndex();
    }

    /**
     * 重新构建索引和词频统计
     */
    public void rebuildIndex() {
        wordFrequency.clear();
        invertedIndex.clear();

        for (int i = 0; i < newsList.size(); i++) {
            NewsItem news = newsList.get(i);
            processNewsText(news, i);
        }
    }

    /**
     * 处理单条新闻文本
     */
    private void processNewsText(NewsItem news, int newsIndex) {
        // 合并标题和内容进行分析
        String text = news.getTitle() + " " + news.getContent();

        // HanLP分词
        List<Term> termList = HanLP.segment(text);

        for (Term term : termList) {
            String word = term.word.trim();
            Nature nature = term.nature;

            // 过滤条件：长度、停用词、词性
            if (isValidWord(word, nature)) {
                // 更新词频统计
                wordFrequency.put(word, wordFrequency.getOrDefault(word, 0) + 1);

                // 更新倒排索引
                invertedIndex
                        .computeIfAbsent(word, k -> new ArrayList<>())
                        .add(newsIndex);
            }
        }
    }

    /**
     * 判断是否为有效词汇
     */
    private boolean isValidWord(String word, Nature nature) {
        return word.length() > 1 &&
                !stopWords.contains(word) &&
                allowedNatures.contains(nature);
    }

    /**
     * 获取热点词汇（按频率排序）
     * @param topN 返回前N个热点词
     */
    public List<HotspotResult> getHotspotWords(int topN) {
        return wordFrequency.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                .limit(topN)
                .map(entry -> {
                    String word = entry.getKey();
                    int freq = entry.getValue();
                    List<NewsItem> relatedNews = getNewsByWord(word);
                    return new HotspotResult(word, freq, relatedNews);
                })
                .collect(Collectors.toList());
    }

    /**
     * 根据词汇获取相关新闻
     */
    public List<NewsItem> getNewsByWord(String word) {
        List<Integer> newsIndexes = invertedIndex.get(word);
        if (newsIndexes == null) {
            return new ArrayList<>();
        }

        return newsIndexes.stream()
                .map(index -> newsList.get(index))
                .collect(Collectors.toList());
    }

    /**
     * 获取包含特定词汇的热点结果
     */
    public Optional<HotspotResult> getHotspotResultByWord(String word) {
        Integer freq = wordFrequency.get(word);
        if (freq == null) {
            return Optional.empty();
        }

        List<NewsItem> relatedNews = getNewsByWord(word);
        return Optional.of(new HotspotResult(word, freq, relatedNews));
    }

    /**
     * 获取总新闻数量
     */
    public int getTotalNewsCount() {
        return newsList.size();
    }

    /**
     * 获取总词汇数量
     */
    public int getTotalVocabularySize() {
        return wordFrequency.size();
    }

    /**
     * 添加自定义停用词
     */
    public void addStopWords(Collection<String> words) {
        stopWords.addAll(words);
        rebuildIndex();
    }

    /**
     * 清空所有数据
     */
    public void clear() {
        newsList.clear();
        wordFrequency.clear();
        invertedIndex.clear();
    }
}